#include "Main.h"

PipeServer* pipe = new PipeServer();

bool PipeServer::ListenConnections()
{
	bool bConnected = false;
	HANDLE hPipe = NULL;

	m_Port.Create(1);

	while(true)
	{
		Sleep(0);
		hPipe = CreateNamedPipe(
			m_cPipeName,
			PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
			PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
			PIPE_UNLIMITED_INSTANCES,
			BUFSIZE, BUFSIZE,
			1000, NULL);

		bConnected = (ConnectNamedPipe(hPipe, 0) == 1) ? true : (GetLastError() == ERROR_PIPE_CONNECTED);

		if(bConnected){
			m_Port.AssociateFile(hPipe, (ULONG_PTR)hPipe);
			LPPIPEINST pOverlapped = (LPPIPEINST)GlobalAlloc(GPTR, sizeof(PIPEINST));
			ReadFile(hPipe,
				&pOverlapped->bmRequest,
				sizeof(pOverlapped->bmRequest),
				&pOverlapped->cbRead,
				(LPOVERLAPPED)pOverlapped);
		}else{
			CloseHandle(hPipe);
		}
	}
	return true;
}

HRESULT PipeServer::ListenConnectedPipes()
{
	DWORD dwRead = 0;
	HRESULT ret = S_OK;
	ULONG_PTR completitionKey = 0;
	LPOVERLAPPED pOverlapped = NULL;
	LPPIPEINST pPipeInst = NULL;

	while (true)
	{
		Sleep(0);
		ret = m_Port.DequeuePacket(INFINITE, dwRead, completitionKey, pOverlapped);
		if (ret != S_OK)
		{
			GlobalFree((HGLOBAL)pOverlapped);
			CloseHandle((HANDLE)completitionKey);
			continue;
		}

		pPipeInst = reinterpret_cast<LPPIPEINST>(pOverlapped);

		BaseMessage& inMessage = pPipeInst->bmRequest;
		BaseMessage& outMessage = pPipeInst->bmReply;

		if (inMessage.header == CA_DisconnectPipe)
		{
			GlobalFree((HGLOBAL)pPipeInst);
			CloseHandle((HANDLE)completitionKey);
			continue;
		}
		if (inMessage.header == CA_IsAlive)
		{
			//Do Nothing
		}
		else if(inMessage.type & IS_COMMAND)
		{
			if (inMessage.header > CA_RequestsBegin)
			{
				if (inMessage.header >= CA_RequestsEnd)
				{
					outMessage.header = 1;
					outMessage.Param1.i = -1;
					outMessage.Param2.i = -1;
					outMessage.Param3.i = -1;
					outMessage.Param4.i = -1;
					outMessage.Param5.i = -1;
					outMessage.type = IS_NUMERIC;
					//Write(hPipe, outMessage);
				}
				else
				{
					if (m_HandleRequestsFunction != NULL)
					{
						m_HandleRequestsFunction(inMessage);
						outMessage = m_CurrResponse;
					}
					else
					{
						outMessage.header = 1;
						outMessage.Param1.i = -1;
						outMessage.Param2.i = -1;
						outMessage.Param3.i = -1;
						outMessage.Param4.i = -1;
						outMessage.Param5.i = -1;
						outMessage.type = IS_NUMERIC;
					}
				}
			}
			else if(inMessage.header <= CA_RequestsBegin)
			{
				if (inMessage.header <= CA_CommandsBegin)
				{
					outMessage.header = 1;
					outMessage.Param1.i = -1;
					outMessage.Param2.i = -1;
					outMessage.Param3.i = -1;
					outMessage.Param4.i = -1;
					outMessage.Param5.i = -1;
					outMessage.type = IS_NUMERIC;
				}
				else
				{
					AddCommand(inMessage);
				}
			}
		}
		else if(inMessage.type & IS_REQUEST)
		{
			ZeroMemory((PVOID)&outMessage, sizeof(outMessage));
			if (inMessage.header < CA_RequestsBegin)
			{
				if (inMessage.header > CA_CommandsBegin)
					AddCommand(inMessage);
				outMessage.header = 1;
				outMessage.Param1.i = -1;
				outMessage.Param2.i = -1;
				outMessage.Param3.i = -1;
				outMessage.Param4.i = -1;
				outMessage.Param5.i = -1;
				outMessage.type = IS_NUMERIC;
				WriteFile((HANDLE)completitionKey,
					&outMessage,
					sizeof(outMessage),
					&pPipeInst->cbWritten,
					NULL);
			}
			else if(inMessage.header >= CA_RequestsEnd)
			{
				outMessage.header = 1;
				outMessage.Param1.i = -1;
				outMessage.Param2.i = -1;
				outMessage.Param3.i = -1;
				outMessage.Param4.i = -1;
				outMessage.Param5.i = -1;
				outMessage.type = IS_NUMERIC;
				WriteFile((HANDLE)completitionKey,
					&outMessage,
					sizeof(outMessage),
					&pPipeInst->cbWritten,
					NULL);
			}
			else
			{
				if (m_HandleRequestsFunction != NULL)
				{
					m_HandleRequestsFunction(inMessage);
					outMessage = m_CurrResponse;
				}
				else
				{
					outMessage.header = 1;
					outMessage.Param1.i = -1;
					outMessage.Param2.i = -1;
					outMessage.Param3.i = -1;
					outMessage.Param4.i = -1;
					outMessage.Param5.i = -1;
					outMessage.type = IS_NUMERIC;
				}
				WriteFile((HANDLE)completitionKey,
					&outMessage,
					sizeof(outMessage),
					&pPipeInst->cbWritten,
					NULL);
			}
		}
		ReadFile((HANDLE)completitionKey,
			&pPipeInst->bmRequest,
			sizeof(pPipeInst->bmRequest),
			&pPipeInst->cbRead,
			pOverlapped);
	}
}